package cn.com.miao.lynx.common.base.service;

import cn.com.miao.lynx.common.base.mapping.BaseMapStructMapping;
import cn.com.miao.lynx.common.base.model.BaseModel;
import cn.com.miao.lynx.common.base.repository.BaseRepository;
import cn.com.miao.lynx.common.core.syntactic.EntityBuilder;
import cn.com.miao.lynx.common.core.util.SpringContextUtil;
import cn.hutool.json.JSONObject;
import com.querydsl.jpa.impl.JPAQueryFactory;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Optional;

/**
 * BaseService
 *
 * @title: BaseService
 * @description:
 * @author: dengmiao
 * @create: 2019-12-23 16:37
 **/
@FunctionalInterface
public interface BaseService <Entity extends BaseModel<ID>, ID extends Serializable> {

    /**
     * 仓储
     * @return 其对应的仓储
     */
    BaseRepository<Entity, ID> getRepository();

    default Class<?> getClazz(int index) {
        // 获取class上的泛型类型
        // Class<E> clazz = (Class <E>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];

        // 获取interface上的泛型类型
        Type[] types = getClass().getInterfaces()[0].getGenericInterfaces();
        ParameterizedType parameterized = (ParameterizedType) types[0];

        return (Class<?>) parameterized.getActualTypeArguments()[index];
    }

    /**
     * jpa query dls 查询工厂
     * @return 查询工厂
     */
    default JPAQueryFactory jpaQueryFactory() {
        return (JPAQueryFactory) SpringContextUtil.getBean(JPAQueryFactory.class);
    }

    /**
     * 获取注入的mapStruct转化bean
     * 非必须 可null
     * @return BaseMapStructMapping
     */
    default BaseMapStructMapping<Entity, ID> getMapStructMapping() {
        return null;
    }

    /**
     * 保存
     * @param entity 标准实体
     * @return 创建后的实体含主键
     */
    default Entity create(Entity entity) {
        return getRepository().save(entity);
    }

    /**
     * 根据ID获取返回实体
     * @param id 主键
     * @return 查询所得实体
     */
    default Entity get(ID id) {
        return getRepository().getOne(id);
    }

    /**
     * 根据ID获取
     * @param id 主键
     * @return 包含查询实体的可空容器对象
     */
    default Optional<Entity> retrieve(ID id) {
        return getRepository().findById(id);
    }

    /**
     * Specification
     * @param spec 查询条件
     * @return 包含查询实体的可空容器对象
     */
    default Optional<Entity> retrieve(Specification<Entity> spec) {
        return getRepository().findOne(spec);
    }

    /**
     * Example
     * @param example 查询条件
     * @return 包含查询实体的可空容器对象
     */
    default Optional<Entity> retrieve(Example example) {
        return getRepository().findOne(example);
    }

    /**
     * 修改
     * @param entity 更新实体
     * @return 更新后的实体
     */
    default Entity update(Entity entity) {
        return getRepository().saveAndFlush(entity);
    }

    /**
     * 批量保存与修改
     * @param entities 实体集合
     * @return 更新后的实体集合
     */
    default Iterable<Entity> saveOrUpdateAll(Iterable<Entity> entities) {
        return getRepository().saveAll(entities);
    }

    /**
     * 删除
     * @param entity 删除的实体
     */
    default void delete(Entity entity) {
        getRepository().delete(entity);
    }

    /**
     * 根据Id删除
     * @param id 删除的id
     */
    default void delete(ID id) {
        getRepository().deleteById(id);
    }

    /**
     * 批量删除
     * @param entities 删除的实体集合
     */
    default void delete(Iterable<Entity> entities) {
        getRepository().deleteAll(entities);
    }

    /**
     * 清空缓存，提交持久化
     */
    default void flush() {
        getRepository().flush();
    }

    /**
     * 根据条件查询获取
     * @param spec 条件
     * @return 查询集合
     */
    default List<Entity> list(Specification<Entity> spec) {
        return getRepository().findAll(spec);
    }

    /**
     * Example
     * @param example 条件
     * @return 查询集合
     */
    default List<Entity> list(Example example) {
        return getRepository().findAll(example);
    }

    /**
     * 获取所有列表
     * @return 查询集合
     */
    default List<Entity> list() {
        return getRepository().findAll();
    }

    /**
     * 分页获取
     * @param pageable 分页条件对象
     * @return 分页结果对象
     */
    default Page<Entity> page(Pageable pageable){
        return getRepository().findAll(pageable);
    }

    /**
     * 根据查询条件分页获取
     * @param spec 条件
     * @param pageable 分页条件对象
     * @return 分页结果对象
     */
    default Page<Entity> page(Specification<Entity> spec, Pageable pageable) {
        return getRepository().findAll(spec, pageable);
    }

    /**
     *
     * @param jsonObject
     * {
     *   "pageNumber": "1",
     *   "pageSize": "10",
     *   "criteria": [{"operator": "like", "field": "name", "value": "aaa"}],
     *   "sort": [{"field":"id","asc":"true"}]
     * }
     * @throws Exception
     */
    default Page<Entity> page(JSONObject jsonObject) throws Exception {
        PageRequest pageRequest = EntityBuilder.Factory.buildPageRequest(jsonObject);
        Specification<Entity> objectSpecification = EntityBuilder.Factory.buildSpecification(jsonObject);
        Page<Entity> all = getRepository().findAll(objectSpecification, pageRequest);
        return all;
    }

    /**
     * 获取总数
     * @return 记录总数
     */
    default Long count() {
        return getRepository().count();
    }

    /**
     * 获取查询条件的结果数
     * @param spec 条件
     * @return 记录总数
     */
    default Long count(Specification<Entity> spec) {
        return getRepository().count(spec);
    }
}
